package com.zzy.controller;

import com.alibaba.fastjson.JSONObject;
import com.zzy.datagridlist.Datagrid;
import com.zzy.model.*;
import com.zzy.service.*;
import com.zzy.util.AjaxMsg;
import com.zzy.util.StatusCode;
import com.zzy.util.UtilJson;
import com.zzy.util.UtilUser;
import com.zzy.util.activiti.ProcessInstanceDiagramCmd;
import com.zzy.util.activiti.UtilFlow;
import com.zzy.util.activiti.Util_Diagrams;
import org.activiti.engine.*;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.*;
import org.activiti.engine.impl.cmd.*;
import org.activiti.engine.impl.context.*;
import org.activiti.engine.impl.interceptor.*;
import org.activiti.engine.impl.persistence.entity.*;
import org.activiti.engine.impl.pvm.*;
import org.activiti.engine.impl.pvm.process.*;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;

import org.activiti.engine.task.TaskQuery;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping("/flow")
public class FlowController {

    @Autowired
    private RepositoryServiceImpl repositoryServiceImpl;
    @Resource
    private ProcessEngine engine;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private UtilService utilService;

    @Autowired
    private DepartService departService;

    @Autowired
    private FlowStepService flowStepService;
    @Autowired
    private FlowAuditService flowAuditService;

    @Autowired
    private LeaveService leaveService;

    /** 跳转到 可以部署的 流程列表首页 */
    @RequestMapping("index")
    public String index(HttpServletRequest request) {
        return "page/flow/flow_index";
    }
    /** 加载可以部署的流程列表数据 */
    @RequestMapping("deploy/gird1")
    @ResponseBody
    public void deployGird1(HttpServletRequest request,HttpServletResponse response) {
        List list = new ArrayList();
        String deployList[] = Util_Diagrams.list();
        int num = 0;
        if (deployList != null) {
            num = deployList.length;
        }
        if(deployList.length>0){
            for(String dep : deployList){
                Map map = new HashMap();
                String name = dep.substring(0  , dep.lastIndexOf(".") );
                map.put("name",name);
                map.put("type","bpmn");//因为都是 bpmn 文件
                map.put("fullName",dep);
                list.add(map);
            }
        }
        int pageSize = 100;
        UtilJson.jsonForLayerUI(list,num,pageSize,response);
    }
    /**
     * 部署流程，需要报表单部署上
     */
    @RequestMapping("deploy")
    public void deployFlow(String processName, HttpServletResponse response) {
        //要判断，是否已经部署，如果已经部署， 部署的流程是否已经结束， 删除还是保留，都是问题
        RepositoryService service = engine.getRepositoryService();
        if (null != processName) {

            // 支持循环部署
            for(String thisName : processName.split(",") ){
                service.createDeployment().addClasspathResource("diagrams/" + thisName).deploy();
            }
           /* if(processName.equals("Bxsp.bpmn")){
                service.createDeployment().addClasspathResource("diagrams/" + processName)
                        .addClasspathResource("form/bxsp.form")
                        .deploy();
            }else if(processName.equals("Hello.bpmn")){//请假表单
                service.createDeployment().addClasspathResource("diagrams/" + processName)
                        .addClasspathResource("form/qingjia.form")
                        .addClasspathResource("form/qingjia_audit.form")
                        .deploy();
            }else{
                service.createDeployment().addClasspathResource("diagrams/" + processName).deploy();
            }*/
        }
        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "success"),response);

    }
    /** 跳转到 已经部署的 流程列表首页 */
    @RequestMapping("deploy/index")
    public String goDeploy(HttpServletRequest request) {
        return "page/flow/flow_deploy";
    }
    /** 加载 已经部署的流程列表数据 */
    @RequestMapping("deploy/gird2")
    @ResponseBody
    public void deployGird2(HttpServletRequest request,HttpServletResponse response) {
        int num = 0;
        RepositoryService service = engine.getRepositoryService();
        List<ProcessDefinition> list = service.createProcessDefinitionQuery().list();
        //这是个接口 所以没有办法 转换成 json 对象。这里 先暂时 手动转换
        List list1 = new ArrayList();
        if (list != null && list.size() > 0) {
            for (ProcessDefinition p : list) {
                Map map = new HashMap();
                map.put("id", p.getId());
                //获取 部署时间
                List deploytimelist = utilService.getListBySql("select DEPLOY_TIME_ from act_re_deployment where ID_=" + p.getDeploymentId());
                String date = deploytimelist.get(0).toString();
                map.put("deployTime", date.substring(0, 19));
                map.put("name", p.getName());
                list1.add(map);
            }
        }
        int pageSize = 100;
        UtilJson.jsonForLayerUI(list1,num,pageSize,response);
    }


    /**
     * 取消部署 流程 即 删除部署
     * @param id
     * @param response
     */
    @RequestMapping("deployed/del")
    public void delDeployed(String id, String flag, HttpServletResponse response) {
        PrintWriter out = null;
        JSONObject json = new JSONObject();

        //判断是否 流程 已经执行
        RepositoryService service = engine.getRepositoryService();
        String state = "";
        try {
            out = response.getWriter();
            //根据 流程 ID 获取当前流程
            ProcessDefinition processDefinition = service.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
            //查询该流程是否已经，启动任务,如果忽略启动，可采取
            //service.deleteDeployment(processDefinition.getDeploymentId(),true);
            //方式删除
            //如果流程 已经启动会生成 一个task
            /*
            // 这种 方法 采用循环 数量大的 情况下 不可取
            List<Task> taskList = engine.getTaskService().createTaskQuery().list();
            for(Task t : taskList){
                if (t.getProcessDefinitionId().equals(id)){//说明 该流程已经启动
                    break;
                }
            }*/
            List list = utilService.getListBySql("select ID_ from act_ru_task where PROC_DEF_ID_ ='"+id+"'");
            if(list!=null && list.size()>0){//流程已经启动 ， 不可以删除
                if(flag!=null && "qz".equals(flag)){//强制删除
                    service.deleteDeployment(processDefinition.getDeploymentId(),true);//强制 级联删除
                    state = "已经清除相关启动的流程，并且取消部署!";
                }else {
                    state = "该流程已经启动，不能撤回！";
                }
            }else{//说明 流程没有启动可以删除
                state = "已经取消部署!";
                service.deleteDeployment(processDefinition.getDeploymentId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        json.put("state", state);
        out.print(json.toString());
    }



    /** 跳转到 可以发起的流程 流程列表首页 */
    @RequestMapping("deployed/index")
    public String goDeployed(HttpServletRequest request) {
        return "page/flow/flow_deployed";
    }
    /**
     * 启动一个流程实例 josn 开启一个流程
     *  这里做两个模式
     * 模式一： 直接和表单绑定 (这样扩展性能不好)
     * 模式二：发起的时候，和表单绑定的话过于麻烦，这里把表单单独分离， 方便管理
     * 暂时按照模式二做，模式一 有时间在做处理
     */
    @RequestMapping("start")
    public void starttask(String flowDepId, Leave leave, HttpServletResponse response) {
        if(StringUtils.hasText(flowDepId)){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            //1. 先启动流程实例
            RuntimeService service = engine.getRuntimeService();
            RepositoryService repositoryService = engine.getRepositoryService();
            RuntimeService runtimeService = engine.getRuntimeService();
            //第一个节点，设置了，发起人的 权限
            Map<String,Object> map = new HashMap<String, Object>();
            //设置下一 操作人为当前人
            User user = UtilUser.getSessionUser();
            map.put("user", user.getId());//流程发起人
            String TYPE_LEAVE = "LEAVE";//给每个流程分一个类 UtilFlow.TYPE_LEAVE
            map.put("businessType", TYPE_LEAVE);//流程的 模块
            //service.startProcessInstanceById(flowId);
            //根据流程Key,查询以部署的流程定义
            String processModelKey = "LEAVE_PRO";//流程图 process 的 ID UtilFlow.KEY_LEAVE

            ProcessDefinition  pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processModelKey).latestVersion().singleResult();
            if(pd==null){
                return;
            }

            String pdId = pd.getId() ;

            //获取全部环节。为流程环节动态添加处理
            List<Map<String, Object>> activities = getCandidateUserExpressions(pdId,repositoryServiceImpl);

            for (Map<String, Object> activity : activities){//循环了 每一个 node
                List<String> candidates = (List<String>) activity.get("candidates");
                if (candidates.isEmpty()){continue;}
                //map.put("state","y");
                for(String cand :candidates){//  找 每一个 node   candidate use..ma separated 的配置
                    System.out.println(cand);
                    String candidate = "";

                    if(cand.equals("all")){//说明这个节点是所有人都可以处理，也就是 上一个节点是谁这个节点 还是谁  注意和candidates.isEmpty()不是一个效果
                        candidate = user.getId();
                        map.put(cand, candidate );
                    }else {
                        //可以把这个设为 某个部门的 id ，根据部门的 id 查询全部人
                        //candidate = departService.getUserIDSByDepartID(user.getDepart());//这个方法暂时未完善
                        map.put(cand, candidate );//放个空字符串防止报错
                    }

                }
            }
            //启动流程
            ProcessInstance pi = runtimeService.startProcessInstanceById(pdId, map);


            //注意 getProcessInstanceId 是 单个发起流程的ID，每发起一次又有一个ID
            pi.getProcessDefinitionId();//是 流程定义的ID，比如很多人都 发起了 LEAVE_PRO:1:204 流程，这个ID 是相同的


            //2. 启动完了之后，第一个节点就有task了
            TaskService taskService = engine.getTaskService();
            List<Task> curTasks = taskService.createTaskQuery().processInstanceId(pi.getProcessInstanceId()).active().list();
            if(curTasks.isEmpty()){//说明 没有查到，有问题了
                return;
            }
            Task task = curTasks.get(0);
            //4. 更新对应表单的节点进度
            if(leave!=null && leave.getId()!=null && leave.getId().equals("")){leave.setId(null);}//保证id为空
            leave.setFlowDepId(flowDepId);//流程定义ID
            leave.setNodeName(task.getName());
            leave.setNodeId(task.getTaskDefinitionKey());
            leave.setTaskId(task.getId());
            leave.setFlowId(pi.getId());//单个流程ID
            leave.setFlowName(pd.getName());
            leave.setState("0");//刚新建
            leave.setCreateTime(sdf.format(new Date()));
            leave.setCreateUserId(user.getId());
            leave.setCreateUserName(user.getName());
            leaveService.save(leave);//保存表单
        }
        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "success"),response);
    }

    /**取消发起*/
    @RequestMapping("unstart")
    public void unStart(String proId,String proName , String formId,HttpServletResponse response) {
        TaskService taskService = engine.getTaskService() ;
        RuntimeService runtimeService = engine.getRuntimeService();
        if(StringUtils.hasText(proId)){
            List<Task> curTasks = taskService.createTaskQuery().processInstanceId(proId).active().list();
            if (curTasks != null && curTasks.size() !=0){ //该流程实例未结束的
                runtimeService.deleteProcessInstance(proId,"");
            }
            // 删除关联信息表
            // 1、 自己定义的 节点过程表和审核信息表
            flowStepService.delByProId(proId);
            // 2、关联 表单的信息
            if(proName!=null){
                if(proName.equals("请假审批")){//删除对应请假流程的表单信息
                    leaveService.del(formId);
                }else if(proName.equals("财务审批")){

                }else if(proName.equals("多人会审")){

                }
            }
            //3、上传的文件等
        }

        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "取消成功"),response);
    }

    /**打开页面设计的窗口的*/
    @RequestMapping("open")
    public String openWin(HttpServletRequest request, String flowDepId,String flowName){
        Leave model = new Leave();//这个随便找个实体就行，主要是用公共的 属性字段，方便一次性 request.setAttribute
        model.setFlowDepId(flowDepId);//流程定义ID
        model.setFlowName(flowName);
        request.setAttribute("model",model);
        request.setAttribute("load",request.getParameter("load"));
        if(flowName.equals("请假审批")){//以后可以从数据库动态 配置
            return "page/leave/leave_detail";
        }else{
            return "redirect:index";
        }
    }
    /**打开 完成任务 加载详情的页面 */
    @RequestMapping("open/complete")
    public String openCompleteWin(String proId,String proName , String formId,HttpServletRequest request){
        request.setAttribute("load", "detail");
        if(proName.equals("请假审批")){//以后可以从数据库动态 配置
            Leave model = leaveService.getByID(formId);
            request.setAttribute("model", model);
            return "page/leave/leave_audit";
        }else{
            return "redirect:index";
        }
    }


    /**
     * 完成当前节点，进入下一环节
     */
    @RequestMapping("complete")
    public void complete (
            @RequestParam(value = "state",required=false)final String state,//审核通过与否
            @RequestParam(value = "opinion",required=false)final String opinion,//审核 意见
            @RequestParam(value = "LastNodeName",required=false)final String LastNodeName,// 上一节点 的节点名称
            @RequestParam(value = "LastNodeId",required=false)final String LastNodeId,// 上一节点 的节点ID
            @RequestParam(value = "flowId",required=false)final String flowId,//流程ID
            @RequestParam(value = "flowDepId",required=false)final String flowDepId,//流程定义ID
            @RequestParam(value = "fromId",required=false)final String fromId,//对应表单的ID //这里只做 请假表单的测试
            @RequestParam(value = "taskId",required=false)final String taskId,//任务ID
            @RequestParam(value = "other",required=false)final String other,//其他参数
            //@RequestParam(value = "file",required=false)final  MultipartFile[] files,
            HttpServletRequest request,
            HttpServletResponse response) {
        User user = UtilUser.getSessionUser();
        String auditUserId = user.getId();
        String auditUserName = user.getName();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String auditTime = sdf.format(new Date());
        Leave leave =  leaveService.getByID(fromId);
        TaskService taskService = engine.getTaskService();
        String auditor = "40281e90673fc8ae01673fc9d3b40001" ;//假设传递过来 下一节点审核人的ID
        //1. 保存本次操作记录
        FlowStep flowStep = new FlowStep();
        flowStep.setFlowDepId(flowDepId);
        flowStep.setAuditor(auditor);
        flowStep.setNodeId(LastNodeId);
        flowStep.setFormId(fromId);
        flowStep.setNodeName(LastNodeName);
        flowStep.setState(state);
        flowStep.setAuditTime(auditTime);
        flowStep.setAuditUserId(auditUserId);
        flowStep.setAuditUserName(auditUserName);
        flowStepService.save(flowStep); //其实历史审核信息 在 act_hi_taskinst  act_hi_actinst 都有体现，不用新建表了 只要 flowAudit 和 这些表 关联即可
        FlowAudit flowAudit = new FlowAudit();
        flowAudit.setAuditUserName(auditUserName);
        flowAudit.setStepId(flowStep.getId());
        flowAudit.setAuditTime(auditTime);
        flowAudit.setAuditUserId(auditUserId);
        flowAudit.setOpinion(opinion);
        flowAuditService.save(flowAudit);

        if(state.equals("y")){
            leave.setState("1");//审核通过
        }else{
            leave.setState("2");//审核驳回，通过流程节点的 state = y 和 n 即可实现 驳回 没有那么麻烦
            //revert();
            //return;
        }

        //获取流程实例
        ProcessDefinition p01 = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(flowId).singleResult();
        //String flowName =  p01.getName() ;// 流程名字
        //2. 完成任务
        //List<Task> list = taskService.createTaskQuery().list();
        Map<String, Object> variables = new HashMap();
        //下一环节审核人
        variables.put("state",state);
        variables.put("manager",auditor);//这里随机设置死一个 账户的ID
        taskService.complete( taskId , variables);
        //4. 更新对应表单的节点进度
        List<Task> curTasks2 = taskService.createTaskQuery().processInstanceId(flowId).active().list();
        if(curTasks2.isEmpty()){//说明流程结束了
            leave.setNodeName(null);
            leave.setNodeId(null);
            leave.setTaskId(null);
            leave.setState("9");//流程结束
        }else{//流程 没有结束
            Task task2 = curTasks2.get(0);
            leave.setNodeName(task2.getName());
            leave.setNodeId(task2.getTaskDefinitionKey());
            leave.setTaskId(task2.getId());
        }
        leaveService.update(leave);//跟新 表单信息

        UtilJson.jsonPrintModel(AjaxMsg.returnAjaxMsg(StatusCode.SUCCESS, "success"),response);
    }



    /** 跳转到 待办 */
    @RequestMapping("db/index")
    public String goDb( HttpServletRequest request, HttpServletResponse response){
        return "page/flow/flow_db";
    }
    /** 获取待办 gird*/
    @RequestMapping("db/grid")
    @ResponseBody
    public void dbGrid( HttpServletRequest request, HttpServletResponse response){
        String businessType = "LEAVE";//这里是请假的， 暂时不分类
        User user = UtilUser.getSessionUser();
        String userId = user.getId();
        TaskService taskService = engine.getTaskService();
        String proIds = "";//有任务的ID集合
        List<Leave> taskList = new ArrayList<Leave>();
        Integer num = 0 ;
        String page =  request.getParameter("page");
        String rows =  request.getParameter("limit");
        Integer p = page == null ? 1 : Integer.valueOf(page);
        Integer r = rows == null ? 10 : Integer.valueOf(rows);



        // 原始的sql 为   INNER  JOIN 不知道为什么 本来是该为 LEFT  JOIN 这里采用 从谢底层sql 的方式 获取

        String taskSql = " SELECT DISTINCT RES.*  FROM  ACT_RU_TASK RES LEFT  JOIN ACT_RU_IDENTITYLINK I ON I.TASK_ID_ = RES.ID_ WHERE  ( RES.ASSIGNEE_ = '"+userId+"'  OR ( RES.ASSIGNEE_ IS NULL AND I.USER_ID_ = '"+userId+"' OR I.GROUP_ID_ IN ( SELECT g.GROUP_ID_   FROM ACT_ID_MEMBERSHIP g WHERE g.USER_ID_ = '"+userId+"' )  )  ) ORDER BY RES.CREATE_TIME_ ASC " ;

        String taskSql2 =  " SELECT DISTINCT RES.* FROM ACT_RU_TASK RES LEFT  JOIN ACT_RU_IDENTITYLINK I ON I.TASK_ID_ = RES.ID_ LEFT JOIN ACT_RU_VARIABLE A0 ON RES.PROC_INST_ID_ = A0.PROC_INST_ID_ WHERE A0.TASK_ID_ IS NULL AND A0.NAME_ = 'businessType' AND A0.TYPE_ = 'string' AND lower(A0.TEXT_) = '"+businessType.toLowerCase()+"' AND ( RES.ASSIGNEE_ = '"+userId+"' OR ( 	RES.ASSIGNEE_ IS NULL AND I.USER_ID_ = '"+userId+"' OR I.GROUP_ID_ IN ( SELECT g.GROUP_ID_ FROM ACT_ID_MEMBERSHIP g WHERE g.USER_ID_ = '"+userId+"')))ORDER BY RES.CREATE_TIME_ ASC " ;




        // 原始的sql 为   INNER  JOIN 不知道为什么 本来是该为 LEFT  JOIN
        /*List<Task> tasks = new ArrayList<Task>();
        if("".equals(businessType)){
            tasks = taskService.createTaskQuery()
                    .taskCandidateOrAssigned(user.getId())
                    .orderByTaskCreateTime().asc().list();
        } else {
            tasks = taskService.createTaskQuery()
                    .taskCandidateOrAssigned(userId)
                   .processVariableValueEqualsIgnoreCase("businessType", businessType)//这里是请假的， 暂时不分类
                    .orderByTaskCreateTime().asc().list();
        }
        if(!tasks.isEmpty()){
            for(Task task :tasks){
                String taskName = task.getName();
                String taskId = task.getId();
                String processInstanceId = task.getProcessInstanceId();
                proIds = "'" + processInstanceId  + "'," + proIds;
            }
            proIds = proIds.substring(0,proIds.length()-1);//去掉最后一个逗号
            proIds = "( " + proIds + " )";
            taskList = leaveService.getPage(" from Leave where flowId in "+proIds ,new Object[]{ },p,r);
            num = leaveService.getTotalNum(" select count(*) from Leave where flowId in "+proIds, new Object[]{ } );
        }*/

        List<Object[]> taskobj = utilService.getListBySql(taskSql2);
        if(!taskobj.isEmpty()){
            for(Object[] arr :taskobj){
                //String taskName = arr[5].toString();
                //String taskId = arr[0].toString();
                String processInstanceId = arr[3].toString();
                proIds = "'" + processInstanceId  + "'," + proIds;
            }
            proIds = proIds.substring(0,proIds.length()-1);//去掉最后一个逗号
            proIds = "( " + proIds + " )";
            taskList = leaveService.getPage(" from Leave where flowId in "+proIds ,new Object[]{ },p,r);
            num = leaveService.getTotalNum(" select count(*) from Leave where flowId in "+proIds, new Object[]{ } );
        }

        UtilJson.jsonForLayerUI(taskList,num,r,response);
    }


    /** 跳转到 进行中 */
    /** 获取待办 gird*/
    @RequestMapping("jxz/index")
    public String goJxz(HttpServletRequest request, HttpServletResponse response){
        RuntimeService service = engine.getRuntimeService();
        //service.startProcessInstanceById(id);
        return "page/flow/flow_jxz";
    }
    /** 获取 进行中 gird*/
    @RequestMapping("jxz/grid")
    @ResponseBody
    public void JxzGrid( HttpServletRequest request, HttpServletResponse response){
        TaskService taskService = engine.getTaskService();
        String businessType = "LEAVE";//这里是请假的， 暂时不分类
        User user = UtilUser.getSessionUser();
        //进行中的，根据用户的权限判断，
        String userRole = user.getRole();
        String sql = " select PROC_INST_ID_  from act_ru_variable where TEXT_ like '%"+user.getId()+"%' ";
        List<Object[]> list0 = utilService.getListBySql(sql);
        String proIds = "";//有任务的ID集合
        List<Leave> taskList = new ArrayList<Leave>();
        Integer num = 0 ;
        String page =  request.getParameter("page");
        String rows =  request.getParameter("limit");
        Integer p = page == null ? 1 : Integer.valueOf(page);
        Integer r = rows == null ? 10 : Integer.valueOf(rows);
        if(!list0.isEmpty()){
            for(Object o :list0){
                proIds = "'" + o  + "'," + proIds;
            }
            proIds = proIds.substring(0,proIds.length()-1);//去掉最后一个逗号
            proIds = "( " + proIds + " )";
            taskList = leaveService.getPage(" from Leave where flowId in "+proIds ,new Object[]{ },p,r);
            num = leaveService.getTotalNum(" select count(*) from Leave where flowId in "+proIds, new Object[]{ } );
        }
        UtilJson.jsonForLayerUI(taskList,num,r,response);
    }

    /** 跳转到 已完结 */
    @RequestMapping("history/index")
    public String goHistory( HttpServletRequest request, HttpServletResponse response){
        RuntimeService service = engine.getRuntimeService();
        List<HistoricProcessInstance> list =  engine.getHistoryService().createHistoricProcessInstanceQuery().list();

        //service.startProcessInstanceById(id);
        return "page/flow/flow_history";
    }
    /** 获取 已完结gird*/
    @RequestMapping("history/grid")
    @ResponseBody
    public void historyGird( HttpServletRequest request, HttpServletResponse response){

        List<HistoricProcessInstance> list =  engine.getHistoryService()
                .createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().asc().list();

        User user = UtilUser.getSessionUser();
        String userId = user.getId();
       /* List<HistoricTaskInstance> listTask = engine.getHistoryService()//与历史数据（历史表）相关的Service
                .createHistoricTaskInstanceQuery()//创建历史任务实例查询
                .taskAssignee(taskAssignee)//指定历史任务的办理人
                .list();*/
        //engine.getHistoryService().createHistoricVariableInstanceQuery();
        // 用sql 直接查询比较方便
        //历史信息包括，
        // 1 流程是当前人发起的
        // 2 当前人只参加的流程某个节点
        // 这里认为 每一个节点都 设置了 处理人
        String sql = " SELECT DISTINCT PROC_INST_ID_ from act_hi_varinst where TEXT_ = '"+userId+"'  ";
        List<Object[]> list0 = utilService.getListBySql(sql);
        String proIds = "";//有任务的ID集合
        List<Leave> taskList = new ArrayList<Leave>();
        Integer num = 0 ;
        String page =  request.getParameter("page");
        String rows =  request.getParameter("limit");
        Integer p = page == null ? 1 : Integer.valueOf(page);
        Integer r = rows == null ? 10 : Integer.valueOf(rows);
        if(!list0.isEmpty()){
            for(Object o :list0){
                proIds = "'" + o  + "'," + proIds;
            }
            proIds = proIds.substring(0,proIds.length()-1);//去掉最后一个逗号
            proIds = "( " + proIds + " )";
            taskList = leaveService.getPage(" from Leave where flowId in "+proIds ,new Object[]{ },p,r);
            num = leaveService.getTotalNum(" select count(*) from Leave where flowId in "+proIds, new Object[]{ } );
        }
        UtilJson.jsonForLayerUI(taskList,num,r,response);


    }

    /**
     * 所有已启动流程实例 图
     */
    @RequestMapping("graphics")
    public void graphics(String definitionId, String instanceId,
                         String taskId, ModelAndView mav, HttpServletResponse response)
            throws IOException {

        response.setContentType("image/png");
        Command<InputStream> cmd = null;

        if (definitionId != null) {
            cmd = new GetDeploymentProcessDiagramCmd(definitionId);
        }

        if (instanceId != null) {
            cmd = new ProcessInstanceDiagramCmd(instanceId);
        }

        if (taskId != null) {
            Task task = engine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
            cmd = new ProcessInstanceDiagramCmd(
                    task.getProcessInstanceId());
        }

        if (cmd != null) {
            InputStream is = engine.getManagementService().executeCommand(cmd);
            int len = 0;
            byte[] b = new byte[1024];
            while ((len = is.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
        }
    }





    /** 获取流程的环节信息*/
    public  List<Map<String,Object>> getCandidateUserExpressions(String processDefinitionId ,RepositoryServiceImpl repositoryService) {
        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();

        if(repositoryService == null) {return null;}
        //获取流程定义的所有环节
        ProcessDefinitionImpl processDefinitionImpl =  (ProcessDefinitionImpl)repositoryService .getDeployedProcessDefinition(processDefinitionId);

        List<ActivityImpl>  activitiList = processDefinitionImpl.getActivities();
        for(ActivityImpl act : activitiList){ //流程节点信息
            Map<String,Object> prop = act.getProperties();//节点属性
            String type = prop.get("type").toString();//节点类型
            if("userTask".equals(type)){
                Map<String,Object> map = new HashMap<String, Object>();
                TaskDefinition td = (TaskDefinition) prop.get("taskDefinition");//任务定义类
                List<String> candidates = getLingCandidates(td);//候选人列表
                map.put("activityId", act.getId());//节点id
                map.put("activityName", prop.get("name"));//节点属性
                map.put("candidates", candidates);//候选人用户表达式
                result.add(map);
            }
        }
        return result;
    }
    /**获取候选人列表*/
    public  List<String> getLingCandidates(TaskDefinition t){
        List<String> candidates = new ArrayList<String>();//候选人列表
        @SuppressWarnings("rawtypes")
        Set set = new HashSet();
        if(t.getCandidateUserIdExpressions().size() > 0){
            set = t.getCandidateUserIdExpressions();
        } else if(t.getCandidateGroupIdExpressions().size() > 0) {
            set = t.getCandidateGroupIdExpressions();
        }
        if(set.size() > 0){
            Object[] objs = set.toArray();
            for(Object obj : objs){
                if(obj != null){
                    String tmp = obj.toString();//格式为${xxx}
                    if(tmp.length() > 3){
                        candidates.add(tmp.substring(2, tmp.length()-1));
                    }
                }
            }
        } else if(t.getAssigneeExpression() != null){
            Object obj = t.getAssigneeExpression();
            if(obj != null){
                String tmp = obj.toString();
                if(tmp.length() > 3){
                    candidates.add(tmp.substring(2, tmp.length()-1));
                }
            }
        }
        return candidates;
    }

}
